home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 1998 #3 / Amiga Plus CD - 1998 - No. 3.iso / pd / spiele / frotz / source / amiga_start.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-11-06  |  12.0 KB  |  478 lines

  1. /*
  2.  * amiga_start.c
  3.  *
  4.  */
  5.  
  6. #include <proto/asl.h>
  7. #include <proto/dos.h>
  8. #include <proto/exec.h>
  9. #include <proto/gadtools.h>
  10. #include <proto/icon.h>
  11. #include <proto/intuition.h>
  12. #include <proto/wb.h>
  13. #include <intuition/intuitionbase.h>
  14. #include <exec/memory.h>
  15. #include <workbench/startup.h>
  16. #include <string.h>
  17. #include "frotz.h"
  18. #include "amiga.h"
  19.  
  20. struct FoundNode
  21. {
  22.   struct Node Node;
  23.   int Release;
  24.   int Serial;
  25.   char PathName[256];
  26. };
  27.  
  28. extern struct WBStartup *WBMessage;
  29. extern struct DiskObject *SaveIcon;
  30. extern struct List *SearchDirs;
  31. extern struct List *ExcludeDirs;
  32. extern struct List *GamesList;
  33. struct List *FoundGames;
  34. struct Screen *StartPubScreen;
  35. struct Window *StartWindow;
  36. struct FileRequester *GameRequester;
  37. struct MsgPort *AppMsgPort;
  38. struct AppWindow *AppWindow;
  39. APTR VisualInfo;
  40. APTR GadgetList;
  41.  
  42. char *GamePattern = "(~(#?.#?)|#?.(dat#?|z?))";
  43. char *SelectTitle = "Select with File Requester";
  44. char ProcessedGamePattern[32];
  45. char GameFilename[MAX_FILE_NAME+1];
  46.  
  47. wbmain(struct WBStartup *wbmsg)
  48. {
  49. static char *args[2] = { "Frotz","-W" };
  50.  
  51.   WBMessage = wbmsg;
  52.   main(2,args);
  53.   exit(0);
  54. }
  55.  
  56. void GetGameFilename(void)
  57. {
  58.   if (WBMessage)
  59.   {
  60.     if (WBMessage->sm_ArgList[0].wa_Lock)
  61.       CurrentDir(WBMessage->sm_ArgList[0].wa_Lock);
  62.     if (SaveIcon = GetDiskObject("Icon.Data"))
  63.     {
  64.       SaveIcon->do_CurrentX = NO_ICON_POSITION;
  65.       SaveIcon->do_CurrentY = NO_ICON_POSITION;
  66.     }
  67.  
  68.     if (WBMessage->sm_NumArgs > 1)
  69.     {
  70.       if (WBMessage->sm_ArgList[1].wa_Lock)
  71.     CurrentDir(WBMessage->sm_ArgList[1].wa_Lock);
  72.       strcpy(GameFilename,WBMessage->sm_ArgList[1].wa_Name);
  73.       return;
  74.     }
  75.   }
  76.  
  77.   if (ScanSearchDirectories())
  78.   {
  79.     if (GameRequester) FreeAslRequest(GameRequester);
  80.     return;
  81.   }
  82.   if (RequestGame(0))
  83.   {
  84.     if (GameRequester) FreeAslRequest(GameRequester);
  85.     return;
  86.   }
  87.  
  88.   DeleteList(&SearchDirs,1,0);
  89.   DeleteList(&ExcludeDirs,1,0);
  90.   DeleteList(&GamesList,1,0);
  91.   exit(0);
  92. }
  93.  
  94. int ScanSearchDirectories(void)
  95. {
  96. struct Node *node;
  97. struct Process *process;
  98. struct Window *old_process_window;
  99. BPTR lock;
  100. int search_return = 0;
  101.  
  102.   if (CreateList(&FoundGames) == 0) return;
  103.   ReadGamesFile();
  104.  
  105.   process = (struct Process *)FindTask(0);
  106.   old_process_window = process->pr_WindowPtr;
  107.   process->pr_WindowPtr = (struct Window *)~0L;
  108.  
  109.   ParsePatternNoCase(GamePattern,ProcessedGamePattern,32);
  110.  
  111.   node = SearchDirs->lh_Head;
  112.   while(node->ln_Succ)
  113.   {
  114.     if (lock = Lock(node->ln_Name,ACCESS_READ)) ScanDirectory(lock);
  115.     node = node->ln_Succ;
  116.   }
  117.  
  118.   process->pr_WindowPtr = old_process_window;
  119.  
  120.   RemoveDuplicateEntries();
  121.   SortEntries();
  122.   if (OpenStartWindow())
  123.   {
  124.     HandleStartWindow();
  125.     search_return = 1;
  126.   }
  127.   CloseStartWindow();
  128.   DeleteList(&FoundGames,1,(HOOKFUNC)DeleteFoundNode);
  129.   return search_return;
  130. }
  131.  
  132. void ScanDirectory(BPTR dir)
  133. {
  134. struct FileInfoBlock *fib;
  135. BPTR old_dir,new_dir;
  136.  
  137.   old_dir = CurrentDir(dir);
  138.  
  139.   if ((fib = AllocDosObject(DOS_FIB,0)) == 0) return;
  140.   Examine(dir,fib);
  141.  
  142.   while (ExNext(dir,fib))
  143.   {
  144.     if (fib->fib_DirEntryType > 0)
  145.     {
  146.       if (new_dir = Lock(fib->fib_FileName,ACCESS_READ))
  147.       {
  148.     TestDirectory(new_dir) ? ScanDirectory(new_dir) : UnLock(new_dir);
  149.       }
  150.     }
  151.     else AddGameList(fib->fib_FileName,dir);
  152.   }
  153.  
  154.   FreeDosObject(DOS_FIB,fib);
  155.   CurrentDir(old_dir);
  156.   UnLock(dir);
  157. }
  158.  
  159. int TestDirectory(BPTR lock)
  160. {
  161. struct Node *node;
  162. char full_dir_path[256];
  163.  
  164.   NameFromLock(lock,full_dir_path,256);
  165.   node = ExcludeDirs->lh_Head;
  166.   while(node->ln_Succ)
  167.   {
  168.     if (stricmp(full_dir_path,node->ln_Name) == 0) return 0;
  169.     node = node->ln_Succ;
  170.   }
  171.   return 1;
  172. }
  173.  
  174. void AddGameList(char *game,BPTR dir)
  175. {
  176. BPTR file;
  177. char *header;
  178. int game_number = -1;
  179.  
  180.   if (MatchPatternNoCase(ProcessedGamePattern,game) == 0) return;
  181.  
  182.   if (header = AllocVec(64,MEMF_CLEAR))
  183.   {
  184.     if (file = Open(game,MODE_OLDFILE))
  185.     {
  186.       Read(file,header,64);
  187.       Close(file);
  188.       game_number = ScanForGame((int)(*((zword *)(header+H_RELEASE))),header+H_SERIAL,(int)(*((zword *)(header+H_CHECKSUM))));
  189.       if (game_number != -1) CreateFoundNode(game_number,dir,game,header);
  190.     }
  191.     FreeVec(header);
  192.   }
  193. }
  194.  
  195. int RequestGame(struct Window *window)
  196. {
  197. int req_return;
  198.  
  199.   if (GameRequester == 0)
  200.   {
  201.     GameRequester = AllocAslRequestTags(ASL_FileRequest,
  202.       ASLFR_RejectIcons,1,
  203.       ASLFR_DoPatterns,1,
  204.       ASLFR_SleepWindow,1,
  205.       ASLFR_TitleText,"Select an Infocom Game",
  206.       ASLFR_InitialPattern,GamePattern,TAG_DONE);
  207.   }
  208.  
  209.   if (GameRequester)
  210.   {
  211.     req_return = AslRequestTags(GameRequester,
  212.       ASLFR_Window,window,TAG_DONE);
  213.     strcpy(GameFilename,GameRequester->fr_Drawer);
  214.     AddPart(GameFilename,GameRequester->fr_File,MAX_FILE_NAME);
  215.     if (req_return) return 1;
  216.   }
  217.   return 0;
  218. }
  219.  
  220. void CreateFoundNode(int game_number,BPTR dir,char *file,char *header)
  221. {
  222. struct FoundNode *node;
  223.  
  224.   if (node = AllocVec(sizeof(struct FoundNode),MEMF_CLEAR))
  225.   {
  226.     node->Node.ln_Name = GetGameTitle(game_number);
  227.     if (game_number >= 0)
  228.       node->Node.ln_Pri = 127-game_number;
  229.     else
  230.       node->Node.ln_Pri = game_number;
  231.     Enqueue(FoundGames,(struct Node *)node);
  232.     NameFromLock(dir,node->PathName,256);
  233.     AddPart(node->PathName,file,256);
  234.     node->Release = (int)(*((zword *)(header+H_RELEASE)));
  235.     node->Serial = SerialNumber(header+H_SERIAL);
  236.     return;
  237.   }
  238.   if (node) FreeVec(node);
  239. }
  240.  
  241. void DeleteFoundNode(struct Node *node)
  242. {
  243. }
  244.  
  245. int OpenStartWindow(void)
  246. {
  247. extern int ScreenWidth, ScreenHeight;
  248. extern int ScaleX, ScaleY;
  249. int x_offset, y_offset;
  250. int gadget_width, length;
  251. int listview_height = 0;
  252. int window_width;
  253. struct Gadget *gadget;
  254. struct Node *node;
  255.  
  256. struct NewGadget listview;
  257. struct NewGadget button;
  258.  
  259.   node = FoundGames->lh_Head;
  260.   if (node->ln_Succ == 0) return 0;
  261.  
  262.   if ((StartPubScreen = LockPubScreen(0)) == 0) return 0;
  263.   GetScreenRatio(StartPubScreen);
  264.  
  265.   if ((VisualInfo = GetVisualInfo(StartPubScreen,TAG_DONE)) == 0) return 0;
  266.   if ((gadget = CreateContext(&GadgetList)) == 0) return 0;
  267.  
  268.   x_offset = SizeX(8);
  269.   y_offset = SizeY(4);
  270.  
  271.   gadget_width = TextLength(&(StartPubScreen->RastPort),SelectTitle,strlen(SelectTitle));
  272.   while (node->ln_Succ)
  273.   {
  274.     length = TextLength(&(StartPubScreen->RastPort),node->ln_Name,strlen(node->ln_Name));
  275.     if (length > gadget_width) gadget_width = length;
  276.  
  277.     if (listview_height < ((ScreenHeight*13)/16)-(StartPubScreen->Font->ta_YSize*4))
  278.       listview_height += StartPubScreen->Font->ta_YSize;
  279.  
  280.     node = node->ln_Succ;
  281.   }
  282.  
  283.   gadget_width += 24;
  284.   window_width = gadget_width+(x_offset*2)+StartPubScreen->WBorLeft+StartPubScreen->WBorRight;
  285.   if (window_width > ScreenWidth)
  286.   {
  287.     window_width = ScreenWidth;
  288.     gadget_width = window_width-(x_offset*2)-StartPubScreen->WBorLeft-StartPubScreen->WBorRight;
  289.   }
  290.  
  291.   if (listview_height < StartPubScreen->Font->ta_YSize*3)
  292.     listview_height = StartPubScreen->Font->ta_YSize*3;
  293.   listview_height += 4;
  294.  
  295.   listview.ng_LeftEdge = StartPubScreen->WBorLeft+x_offset;
  296.   listview.ng_TopEdge = StartPubScreen->WBorTop+StartPubScreen->Font->ta_YSize+1+y_offset;
  297.   listview.ng_Width = gadget_width;
  298.   listview.ng_Height = listview_height;
  299.   listview.ng_GadgetText = 0;
  300.   listview.ng_TextAttr = StartPubScreen->Font;
  301.   listview.ng_GadgetID = 1;
  302.   listview.ng_Flags = 0;
  303.   listview.ng_VisualInfo = VisualInfo;
  304.   listview.ng_UserData = 0;
  305.   gadget = CreateGadget(LISTVIEW_KIND,gadget,&listview,
  306.     GTLV_Labels,FoundGames,
  307.     GTLV_ScrollWidth,16,
  308.     TAG_DONE);
  309.   if (gadget == 0) return 0;
  310.  
  311.   button.ng_LeftEdge = listview.ng_LeftEdge;
  312.   button.ng_TopEdge = listview.ng_TopEdge+listview.ng_Height+y_offset;
  313.   button.ng_Width = gadget_width;
  314.   button.ng_Height = StartPubScreen->Font->ta_YSize+4;
  315.   button.ng_GadgetText = SelectTitle;
  316.   button.ng_TextAttr = StartPubScreen->Font;
  317.   button.ng_GadgetID = 2;
  318.   button.ng_Flags = PLACETEXT_IN;
  319.   button.ng_VisualInfo = VisualInfo;
  320.   button.ng_UserData = 0;
  321.   gadget = CreateGadget(BUTTON_KIND,gadget,&button,TAG_DONE);
  322.   if (gadget == 0) return 0;
  323.  
  324.   StartWindow = OpenWindowTags(0,
  325.     WA_Left,(ScreenWidth-window_width)/2,
  326.     WA_Top,StartPubScreen->BarHeight+(StartPubScreen->Font->ta_YSize/2)+2,
  327.     WA_Width,window_width,
  328.     WA_Height,button.ng_TopEdge+button.ng_Height+y_offset+StartPubScreen->WBorBottom,
  329.     WA_IDCMP,IDCMP_CLOSEWINDOW|IDCMP_GADGETUP|LISTVIEWIDCMP|BUTTONIDCMP,
  330.     WA_Gadgets,GadgetList,
  331.     WA_Activate,1,
  332.     WA_RMBTrap,1,
  333.     WA_CloseGadget,1,
  334.     WA_DragBar,1,
  335.     WA_DepthGadget,1,
  336.     WA_AutoAdjust,1,
  337.     WA_Title,"Frotz",
  338.     WA_ScreenTitle,"Select an Infocom game to load.",
  339.     TAG_DONE);
  340.   if (StartWindow == 0) return 0;
  341.   GT_RefreshWindow(StartWindow,0);
  342.  
  343.   if ((AppMsgPort = CreateMsgPort()) == 0) return 0;
  344.   if ((AppWindow = AddAppWindowA(0,0,StartWindow,AppMsgPort,0)) == 0)
  345.     return 0;
  346.  
  347.   return 1;
  348. }
  349.  
  350. void CloseStartWindow(void)
  351. {
  352.   if (AppWindow) RemoveAppWindow(AppWindow);
  353.   if (AppMsgPort) DeleteMsgPort(AppMsgPort);
  354.   if (StartWindow) CloseWindow(StartWindow);
  355.   if (GadgetList) FreeGadgets(GadgetList);
  356.   if (VisualInfo) FreeVisualInfo(VisualInfo);
  357.   if (StartPubScreen) UnlockPubScreen(0,StartPubScreen);
  358. }
  359.  
  360. void HandleStartWindow(void)
  361. {
  362. struct IntuiMessage *imsg;
  363. struct AppMessage *amsg;
  364. struct FoundNode *node;
  365. USHORT code, qualifier, apptype;
  366. ULONG class;
  367. APTR addr;
  368.  
  369.   while(1)
  370.   {
  371.     while (imsg = GT_GetIMsg(StartWindow->UserPort))
  372.     {
  373.       class = imsg->Class;
  374.       code = imsg->Code;
  375.       qualifier = imsg->Qualifier;
  376.       addr = imsg->IAddress;
  377.       GT_ReplyIMsg(imsg);
  378.  
  379.       switch (class)
  380.       {
  381.     case IDCMP_CLOSEWINDOW:
  382.       CloseStartWindow();
  383.       DeleteList(&FoundGames,1,(HOOKFUNC)DeleteFoundNode);
  384.       DeleteList(&SearchDirs,1,0);
  385.       DeleteList(&ExcludeDirs,1,0);
  386.       DeleteList(&GamesList,1,0);
  387.       if (GameRequester) FreeAslRequest(GameRequester);
  388.       exit(0);
  389.       break;
  390.     case IDCMP_GADGETUP:
  391.       switch(((struct Gadget *)addr)->GadgetID)
  392.       {
  393.         case 1:
  394.           node = (struct FoundNode *)FoundGames->lh_Head;
  395.           while (code > 0)
  396.           {
  397.         node = (struct FoundNode *)node->Node.ln_Succ;
  398.         code--;
  399.           }
  400.           if (qualifier & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT))
  401.           {
  402.         Requester(StartWindow,"%s\nRelease %ld / Serial no. %ld\n\n%s","Continue",
  403.           node->Node.ln_Name,node->Release,node->Serial,node->PathName);
  404.           }
  405.           else
  406.           {
  407.         strcpy(GameFilename,node->PathName);
  408.         return;
  409.           }
  410.           break;
  411.         case 2:
  412.           if (RequestGame(StartWindow)) return;
  413.           break;
  414.       }
  415.       break;
  416.       }
  417.     }
  418.     while (amsg = (struct AppMessage *)GetMsg(AppMsgPort))
  419.     {
  420.       if ((apptype = amsg->am_Type) == AMTYPE_APPWINDOW)
  421.       {
  422.     if (amsg->am_ArgList[0].wa_Lock)
  423.       NameFromLock(amsg->am_ArgList[0].wa_Lock,GameFilename,MAX_FILE_NAME);
  424.     AddPart(GameFilename,amsg->am_ArgList[0].wa_Name,MAX_FILE_NAME);
  425.       }
  426.       ReplyMsg((struct Message *)amsg);
  427.       if (apptype == AMTYPE_APPWINDOW) return;
  428.     }
  429.     Wait(PORTSIG(StartWindow->UserPort)|PORTSIG(AppMsgPort));
  430.   }
  431. }
  432.  
  433. void RemoveDuplicateEntries(void)
  434. {
  435. struct FoundNode *current_node;
  436. struct FoundNode *next_node;
  437.  
  438.   current_node = (struct FoundNode *)FoundGames->lh_Head;
  439.   while (current_node->Node.ln_Succ)
  440.   {
  441.     next_node = (struct FoundNode *)current_node->Node.ln_Succ;
  442.     while ((next_node->Node.ln_Succ) && (current_node->Node.ln_Pri == next_node->Node.ln_Pri))
  443.     {
  444.       Remove((struct Node *)next_node);
  445.       FreeVec(next_node);
  446.       next_node = (struct FoundNode *)current_node->Node.ln_Succ;
  447.     }
  448.     current_node = (struct FoundNode *)current_node->Node.ln_Succ;
  449.   }
  450. }
  451.  
  452. void SortEntries(void)
  453. {
  454. struct FoundNode *node;
  455. struct FoundNode *next_node;
  456. struct FoundNode *previous_node;
  457. struct FoundNode *compare_node;
  458.  
  459.   node = (struct FoundNode *)FoundGames->lh_Head;
  460.   while (node->Node.ln_Succ)
  461.   {
  462.     if (node->Node.ln_Pri < 0)
  463.     {
  464.       compare_node = (struct FoundNode *)FoundGames->lh_Head;
  465.       while ((compare_node != node) && (strcmp(compare_node->Node.ln_Name,node->Node.ln_Name) < 0))
  466.     compare_node = (struct FoundNode *)compare_node->Node.ln_Succ;
  467.  
  468.       previous_node = (struct FoundNode *)compare_node->Node.ln_Pred;
  469.       next_node = (struct FoundNode *)node->Node.ln_Succ;
  470.  
  471.       Remove((struct Node *)node);
  472.       Insert(FoundGames,(struct Node *)node,(struct Node *)previous_node);
  473.       node = next_node;
  474.     }
  475.     else node = (struct FoundNode *)node->Node.ln_Succ;
  476.   }
  477. }
  478.